package chat.server.statemachine;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import chat.statemachine.AbstractContent;
import chat.statemachine.AlgorithmActionInterface;
import chat.statemachine.AlgorithmActionInvocationException;
import chat.server.ChatServerState;
import chat.server.statemachine.election.AlgorithmElection;
import chat.server.statemachine.identity.AlgorithmIdentity;
import chat.server.statemachine.mutex.AlgorithmMutex;
import chat.server.statemachine.termin.AlgorithmTermin;

public enum ListOfAlgorithms {
	ALGORITHM_ELECTION(AlgorithmElection.mapOfActions),
	ALGORITHM_IDENTITY(AlgorithmIdentity.mapOfActions),
	ALGORITHM_MUTEX(AlgorithmMutex.mapOfActions),
	ALGORITHM_TERMIN(AlgorithmTermin.mapOfActions);

	public final static int CHAT_SERVER_START_INDEX = 0;

	private final Map<Integer, ? extends AlgorithmActionInterface> mapOfActions;
	private final static List<Map<Integer, ? extends AlgorithmActionInterface>> privateMapOfAlgorithms = new Vector<Map<Integer, ? extends AlgorithmActionInterface>>();
	public final static List<Map<Integer, ? extends AlgorithmActionInterface>> mapOfAlgorithms = Collections
			.unmodifiableList(privateMapOfAlgorithms);

	static {
		for (ListOfAlgorithms am : ListOfAlgorithms
				.values()) {
			privateMapOfAlgorithms.add(am.mapOfActions);
		}
	}

	private ListOfAlgorithms(
			Map<Integer, ? extends AlgorithmActionInterface> map) {
		mapOfActions = map;
	}

	public static void execute(final ChatServerState state,
			final int actionIndex, final Object content)
			throws AlgorithmActionInvocationException {
		boolean executed = false;
		for (Iterator<Map<Integer, ? extends AlgorithmActionInterface>> protocols = mapOfAlgorithms
				.iterator(); protocols.hasNext();) {
			Map<Integer, ? extends AlgorithmActionInterface> protocol = protocols
					.next();
			for (Iterator<? extends AlgorithmActionInterface> actions = protocol
					.values().iterator(); actions.hasNext();) {
				AlgorithmActionInterface action = actions.next();
				if (action.getActionIndex() == actionIndex) {
					executed = true;
					AbstractContent c;
					if (content instanceof AbstractContent) {
						c = (AbstractContent) content;
					} else {
						throw new AlgorithmActionInvocationException(
								"The content is not of type AbstractContent: "
										+ content.getClass().getName());
					}
					action.execute(state, c);
				}
			}
		}
		if (!executed) {
			throw new AlgorithmActionInvocationException("Unknown action: "
					+ actionIndex);

		}
	}
}